package com.hawk.eye.server.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hawk.eye.framework.utils.CollectionUtil;
import com.hawk.eye.framework.utils.ExceptionUtils;
import com.hawk.eye.framework.utils.SecurityUtils;
import com.hawk.eye.framework.utils.StreamUtil;
import com.hawk.eye.common.page.PageQuery;
import com.hawk.eye.common.page.PageResult;
import com.hawk.eye.server.constant.ProblemStatus;
import com.hawk.eye.server.constant.CreateProblemStatusEnum;
import com.hawk.eye.server.convert.ServiceProblemConvert;
import com.hawk.eye.server.delegate.LogMessageStorageDelegate;
import com.hawk.eye.server.domain.dto.req.DictReqDTO;
import com.hawk.eye.server.domain.dto.req.ProblemRecordReqDTO;
import com.hawk.eye.server.domain.dto.req.RepairProblemReqDTO;
import com.hawk.eye.server.domain.dto.resp.DictDataRespDTO;
import com.hawk.eye.server.domain.dto.resp.ProblemRecordRespDTO;
import com.hawk.eye.server.domain.dto.resp.RepairProblemRespDTO;
import com.hawk.eye.api.storage.dto.ServiceLogRespDTO;
import com.hawk.eye.server.domain.po.ProblemRecord;
import com.hawk.eye.server.domain.po.RepairToProblem;
import com.hawk.eye.server.domain.po.ServiceConfig;
import com.hawk.eye.server.mapper.RepairToLogMapper;
import com.hawk.eye.server.mapper.ServiceProblemMapper;
import com.hawk.eye.server.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @className: ServiceProblemServiceImpl
 * @description:
 * @author: salad
 * @date: 2023/10/1
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class ServiceProblemServiceImpl extends ServiceImpl<ServiceProblemMapper, ProblemRecord> implements IServiceProblemService {

    private final LogMessageStorageDelegate logStorageDelegate;

    private final IServiceConfigService serviceConfigService;

    private final IAlarmBaseLogService alarmBaseLogService;

    private final IDictService dictService;

    private final RepairToLogMapper repairToLogMapper;

    @Override
    public PageResult<ProblemRecordRespDTO> page(PageQuery pageQuery, ProblemRecordReqDTO reqDTO) {
        if (reqDTO.getDisposeUser() != null && reqDTO.getDisposeUser() == -1L) {
            reqDTO.setDisposeUser(SecurityUtils.getUserId());
        }
        IPage<ProblemRecordRespDTO> pages = baseMapper.page(pageQuery.toPage(), reqDTO);
        return PageResult.of(pages);
    }

    @Override
    public PageResult<RepairProblemRespDTO> repairProblemPage(PageQuery pageQuery, RepairProblemReqDTO reqDTO) {
        List<Long> problemIdList = new ArrayList<>();
        if (reqDTO.getRepairId() != null) {
            List<RepairToProblem> repairToProblems = repairToLogMapper.selectListByRepairId(reqDTO.getRepairId());
            problemIdList = StreamUtil.mapToList(repairToProblems.stream(), RepairToProblem::getProblemId);
        }
        IPage<RepairProblemRespDTO> pages = baseMapper.repairProblemPage(pageQuery.toPage(), reqDTO);
        if (reqDTO.getRepairId() != null) {
            for (RepairProblemRespDTO record : pages.getRecords()) {
                if (problemIdList.contains(record.getId())) {
                    record.setFirstProblem(1);
                }
            }
        }
        return PageResult.of(pages);
    }

    @Override
    public boolean createLogProblem(ProblemRecordReqDTO reqDTO) {
        ExceptionUtils.isEmptyThrow(reqDTO.getBaseAlarmId(), "参数{}不允许为空", "baseAlarmId");
        int row = baseMapper.insert(ServiceProblemConvert.INSTANCE.to(reqDTO));
        ExceptionUtils.isTrueThrow(row != 1, "新建缺陷失败，请稍后重试");
        return alarmBaseLogService.updateProblemStatus(reqDTO.getBaseAlarmId(), CreateProblemStatusEnum.CREATED);
    }

    @Override
    public boolean update(ProblemRecordReqDTO reqDTO) {
        ExceptionUtils.isEmptyThrow(reqDTO.getId(), "参数{}不允许为空", "id");
        return updateById(ServiceProblemConvert.INSTANCE.to(reqDTO));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean activate(Long[] ids) {
        List<ProblemRecord> problemRecords = listByIds(CollectionUtil.toList(ids));
        if (CollectionUtil.isEmpty(problemRecords)) {
            return false;
        }
        for (ProblemRecord problemRecord : problemRecords) {
            problemRecord.setStatus(ProblemStatus.UNSOLVED);
        }
        return updateBatchById(problemRecords);
    }

    @Override
    public boolean resolve(Long[] ids) {
        List<ProblemRecord> problemRecords = listByIds(CollectionUtil.toList(ids));
        if (CollectionUtil.isEmpty(problemRecords)) {
            return false;
        }
        for (ProblemRecord problemRecord : problemRecords) {
            if(problemRecord.getResolveTime() == null){
                problemRecord.setResolveTime(LocalDateTime.now());
            }
            problemRecord.setStatus(ProblemStatus.RESOLVED);
        }
        return updateBatchById(problemRecords);
    }

    @Override
    public boolean close(Long[] ids) {
        List<ProblemRecord> problemRecords = listByIds(CollectionUtil.toList(ids));
        if (CollectionUtil.isEmpty(problemRecords)) {
            return false;
        }
        for (ProblemRecord problemRecord : problemRecords) {
            problemRecord.setStatus(ProblemStatus.CLOSE);
        }
        return updateBatchById(problemRecords);
    }

    @Override
    public ProblemRecordRespDTO detail(Long id) {
        ProblemRecord problemRecord = getById(id);
        ExceptionUtils.isEmptyThrow(problemRecord, "缺陷不存在或已删除");
        Long serviceId = problemRecord.getServiceId();
        ServiceConfig serviceConfig = serviceConfigService.getById(serviceId);
        Long baseAlarmId = problemRecord.getBaseAlarmId();
        ServiceLogRespDTO detail = logStorageDelegate.getAlarmLogStorage().detail(baseAlarmId);
        return ServiceProblemConvert.INSTANCE.to(problemRecord, detail, serviceConfig);
    }

    @Override
    public ProblemRecordRespDTO detailByLog(Long baseAlarmId) {
        ProblemRecord pr = getOne(Wrappers.<ProblemRecord>lambdaQuery()
                .eq(ProblemRecord::getBaseAlarmId, baseAlarmId)
                .orderByAsc(ProblemRecord::getCreateTime).last("limit 1"));
        ExceptionUtils.isEmptyThrow(pr, "缺陷不存在或已删除");
        Long serviceId = pr.getServiceId();
        ServiceConfig serviceConfig = serviceConfigService.getById(serviceId);
        ServiceLogRespDTO detail = logStorageDelegate.getAlarmLogStorage().detail(baseAlarmId);
        return ServiceProblemConvert.INSTANCE.to(pr, detail, serviceConfig);
    }

    @Override
    public List<DictDataRespDTO> problemDictList() {
        DictReqDTO reqDTO = new DictReqDTO();
        return dictService.dictDataList(reqDTO);
    }

    @Override
    public boolean saveDict(DictReqDTO reqDTO) {
        return dictService.saveDict(reqDTO);
    }

    @Override
    public boolean updateDict(DictReqDTO reqDTO) {
        return dictService.updateDict(reqDTO);
    }

    @Override
    public boolean removeDict(Long[] ids) {
        return dictService.removeDict(ids);
    }

    @Override
    public List<DictDataRespDTO> dictListByType(String type) {
        return dictService.dictListByType(type);
    }

    @Override
    public List<ProblemRecord> getProblemListByRepairId(Long id) {
        return baseMapper.getProblemListByRepairId(id);
    }

}
